package xconsole

import (
	"encoding/json"
	"flag"
	"fmt"
	"strings"

	"gitee.com/xiaoyutab/xgotool/xstring"
)

// 接口封装函数，用于将HTTP接口封装成可以灵活使用的请求信息
// PS: 只需要少许的改动，即可完成接口文件的封装
func interfaceEncapsulation(help bool) string {
	if help {
		return "接口封装函数，用于将HTTP接口封装成可以灵活使用的请求信息（限制JSON返回值）"
	}
	http_url := ""
	quest_methods := ""
	jsons := ""
	f := ""
	flag.StringVar(&http_url, "uri", "", "接口请求地址")
	flag.StringVar(&quest_methods, "methods", "GET", "请求方式，允许值：GET、POST")
	flag.StringVar(&f, "file", "", "写入到文件中（此处传目录），空表示直接输出到控制台")
	flag.Parse()
	fmt.Println("请手动输入JSON文本(为方便复制粘贴，此处采用空内容结束，即输入完成后需要按两次回车): ")
	fmt.Println("PS: 由于实现逻辑，暂不支持上下左右键仅限方向调整；且由于横向长度限制，过长的json建议分行输入")
	for {
		tmp := ""
		fmt.Scanln(&tmp)
		if tmp == "" {
			// 结束
			break
		}
		jsons += tmp
	}
	out := "\n// 函数名，此处需要进行修改\nfunc Quest_" + xstring.MD5("这是要生成的函数名随机数")
	out_struct := `// 包名，此处需要进行修改
	package temp_` + xstring.MD5("这是要生成的包名随机数") + `

	import (
		"encoding/json"

		"gitee.com/xiaoyutab/xgotool/https"
		"gitee.com/xiaoyutab/xgotool/xerror"
		"gitee.com/xiaoyutab/xgotool/xstring"
	)`
	// 处理https请求
	out += "()(*ReturnResult,error){\n// 请求方法，此处需要进行修改\nh := https."
	switch strings.ToLower(quest_methods) {
	case "get":
		out += "Get"
	case "post":
		out += "Post"
	case "postjson":
		out += "PostJson"
	default:
		out += "get"
	}
	out += "(\"" + http_url + "\", nil, nil)\n"
	out += "// 错误判断\n"
	out += "if h.Error != nil {\n\treturn nil,xerror.To(h.Error)\n}\n"
	out += "// 返回值判断\n"
	out += "if h.HttpCode <= 200 || h.HttpCode >= 300 {\n\treturn nil,xerror.NewFmt(\"Http Code判断错误：%d\", h.HttpCode)\n}\n"
	out += "// 接口返回值定义\n"
	out += "// " + jsons + "\n"
	var l []any
	var m map[string]any
	// JSON转GO结构体
	err := json.Unmarshal([]byte(jsons), &m)
	if err != nil {
		err := json.Unmarshal([]byte(jsons), &l)
		if err != nil {
			panic("JSON转换失败：" + err.Error())
		}
	}
	out += strings.ReplaceAll(strings.ReplaceAll(json2struct(m, l, "temp_http_struct", true), "\n\n", ""), "TempHttpStruct", "tempHttpStruct")
	out_struct += "\n// 函数返回值定义\n// 类型定义，此处需要进行修改"
	out_struct += strings.ReplaceAll(json2struct(m, l, "return_result", false), "\n\n", "")
	out += "\n// 返回值扫描到对象中\n// 类型转换，此处需要进行修改"
	out += "\ntemp := tempHttpStruct{}\nif err := h.Json(&temp);err != nil{\n\treturn nil,xerror.To(err)\n}"
	out += "\n\n// 将返回值追加到正常的返回对象中\nresult := ReturnResult{}\n"
	out += json2eq(m, l, "tempHttpStruct", "ReturnResult", "temp", "result")
	out += "\n// 返回正常对象信息\n// 业务逻辑判断，此处需要进行修改\nreturn &result,nil\n}"
	// 写入到文件中
	writeFile(f, out_struct+out)
	fmtFunction(f)
	return ""
}

// JSON类型转go结构体字符串，以便输出到屏幕上
//
//	m	待转换的map结构体
//	l	待转换的list列表
//	old	旧对象名称
//	new	新对象名称
//	op	旧变量名称
//	np	新变量名称
func json2eq(m map[string]any, l []any, old, new, op, np string) string {
	outs := ""
	if len(m) > 0 {
		// 结构体为一个map数组
		for k, v := range m {
			tp := any2type(v, false, false)
			if tp == "any" {
				if vvv, ok := v.(map[string]any); ok {
					outs += json2eq(vvv, nil, old, new, op+"."+xstring.CamelCase(k), "\t"+np+"."+xstring.CamelCase(k))
				}
			} else if tp == "[]any" {
				// 如果还是复合类型变量的话
				if vv, ok := v.([]any); ok {
					if vvv, ok := vv[0].(map[string]any); ok {
						ti := "i_" + xstring.MD5(fmt.Sprintf("%T: %v", vvv, vvv))
						outs += "for " + ti + " := 0; " + ti + " < len(" + op + "." + xstring.CamelCase(k) + "); " + ti + " ++{\n"
						outs += json2eq(vvv, nil, old, new, op+"."+xstring.CamelCase(k)+"["+ti+"]", "\t"+np+"."+xstring.CamelCase(k)+"["+ti+"]")
						outs += "}\n"
					}
				}
			} else {
				// 普通类型变量，直接就进行赋值即可
				if tp == "int64" {
					outs += np + "." + xstring.CamelCase(k) + " = xstring.JInt64(" + op + "." + xstring.CamelCase(k) + ")\n"
				} else if tp == "float64" {
					outs += np + "." + xstring.CamelCase(k) + " = xstring.JFloat64(" + op + "." + xstring.CamelCase(k) + ")\n"
				} else {
					outs += np + "." + xstring.CamelCase(k) + " = " + op + "." + xstring.CamelCase(k) + "\n"
				}
			}
		}
	} else if len(l) > 0 {
		outs += any2type(l[0], true, false)
	}
	return outs
}
